package com.example.demo.config.security;

import cn.hutool.json.JSONUtil;
import com.example.demo.config.jwt.JwtFilter;
import com.example.demo.constant.CommonConstants;
import com.example.demo.service.MyUserService;
import com.example.demo.config.security.login.sms.SmsAuthenticationFilter;
import com.example.demo.config.security.login.sms.SmsAuthenticationProvider;
import com.example.demo.config.security.login.usernamepassword.JsonLoginFilter;
import com.example.demo.config.security.login.usernamepassword.KaptchaAuthenticationProvider;
import com.example.demo.util.R;
import com.example.demo.util.jwt.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.context.HttpSessionSecurityContextRepository;
import org.springframework.security.web.context.SecurityContextHolderFilter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Configuration
@Slf4j
public class MySecurityConfig {
    @Autowired
    MyUserService myUserService;

    @Autowired
    JwtFilter jwtFilter;

    @Autowired
    StringRedisTemplate redisTemplate;
//    @Bean
//    public PasswordEncoder passwordEncoder() {
//        return new BCryptPasswordEncoder();
//    }

//    @Bean
//    public JdbcUserDetailsManager jdbcUserDetailsManager(JdbcTemplate jdbcTemplate) {
//        JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager();
//        jdbcUserDetailsManager.setJdbcTemplate(jdbcTemplate);
//        if (!jdbcUserDetailsManager.userExists("baibai")) {
//            jdbcUserDetailsManager.createUser(User.withUsername("baibai").password("{noop}123").roles("admin").build());
//        }
//        if (!jdbcUserDetailsManager.userExists("baibai1")) {
//            jdbcUserDetailsManager.createUser(User.withUsername("baibai1").password("{noop}123").roles("user").build());
//        }
//        if (!jdbcUserDetailsManager.userExists("baibai2")) {
//            jdbcUserDetailsManager.createUser(User.withUsername("baibai2").password("{noop}123").roles("user1").build());
//        }
//        return jdbcUserDetailsManager;
//    }

//    @Bean
    JsonLoginFilter jsonFilter(){
        JsonLoginFilter jsonLoginFilter = new JsonLoginFilter();
        jsonLoginFilter.setUsernameParameter("uname_login_2type_filter");
        jsonLoginFilter.setPasswordParameter("pwd_login_2type_filter");
        jsonLoginFilter.setFilterProcessesUrl("/login_2type_filter");
        jsonLoginFilter.setAuthenticationSuccessHandler((req, resp, authentication) ->{
            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            resp.setCharacterEncoding("utf-8");
            String jsonStr = JSONUtil.toJsonStr(R.ok(authentication));
            resp.getWriter().write(jsonStr);
        });
        jsonLoginFilter.setAuthenticationFailureHandler((req,resp,authException) ->{
            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            resp.setCharacterEncoding("utf-8");
            String jsonStr = JSONUtil.toJsonStr(R.failed(authException.getMessage()));
            resp.getWriter().write(jsonStr);
        });
        //配置securitycontext的存储策略，如果没有自定义jsonfilter，系统将自动配置usernamepasswordAuthenticationfilter围棋配置
        //现在我们配置了jsonfilter，就需要我们配置存储策略了。会出现这种情况，用户登录了以后，访问接口，出现没有登录的情况，然后系统自动跳转到登陆页面（postman会提示，Authentication method not supported: GET）
        jsonLoginFilter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
        jsonLoginFilter.setAuthenticationManager(myAuthenticationProviders());
        return jsonLoginFilter;
    }

//    @Bean
        SmsAuthenticationFilter smsAuthenticationFilter(){
        SmsAuthenticationFilter smsAuthenticationFilter = new SmsAuthenticationFilter();
            smsAuthenticationFilter.setPhoneParameter("phone_smsAuthenticationFilter");
            smsAuthenticationFilter.setCodeParameter("code_smsAuthenticationFilter");
            smsAuthenticationFilter.setFilterProcessesUrl("/login_sms");
            smsAuthenticationFilter.setAuthenticationSuccessHandler((req, resp, authentication) ->{
            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            resp.setCharacterEncoding("utf-8");
            String jsonStr = JSONUtil.toJsonStr(R.ok(authentication));
            resp.getWriter().write(jsonStr);
        });
            smsAuthenticationFilter.setAuthenticationFailureHandler((req,resp,authException) ->{
            resp.setContentType(MediaType.APPLICATION_JSON_VALUE);
            resp.setCharacterEncoding("utf-8");
            String jsonStr = JSONUtil.toJsonStr(R.failed(authException.getMessage()));
            resp.getWriter().write(jsonStr);
            log.error("登录失败：{}",authException);
        });
        //配置securitycontext的存储策略，如果没有自定义jsonfilter，系统将自动配置usernamepasswordAuthenticationfilter围棋配置
        //现在我们配置了jsonfilter，就需要我们配置存储策略了。会出现这种情况，用户登录了以后，访问接口，出现没有登录的情况，然后系统自动跳转到登陆页面（postman会提示，Authentication method not supported: GET）
            smsAuthenticationFilter.setSecurityContextRepository(new HttpSessionSecurityContextRepository());
            smsAuthenticationFilter.setAuthenticationManager(myAuthenticationProviders());
        return smsAuthenticationFilter;
    }


    /**
     * 内存用户
     * 如果配置文件和此处都配置了账号密码，配置文件里的配置是不生效的
     * spring.security.user.name=user
     * spring.security.user.password=123456
     * @return
     */
//    @Bean
//    public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
//        Collection<UserDetails> collection = new ArrayList<>();
//        collection.add(User.withUsername("baibai").password("{noop}123").roles("admin").build());
//        collection.add(User.withUsername("baibai1").password("{noop}123").roles("admin").build());
//        return new InMemoryUserDetailsManager(collection);
////        return new InMemoryUserDetailsManager(User.withUsername("baibai")
////                //｛noop｝代表密码没有加密
////                .password("{noop}123")
////                .build());
//    }

    /**
     * 配置seccurity过滤连
     * o.s.s.web.DefaultSecurityFilterChain     : Will secure any request with
     * [org.springframework.security.web.session.DisableEncodeUrlFilter@1dd74143
     * , org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@526a9908
     * , org.springframework.security.web.context.SecurityContextHolderFilter@2d55e826
     * , org.springframework.security.web.header.HeaderWriterFilter@5626d18c
     * , org.springframework.security.web.csrf.CsrfFilter@290e8cab
     * , org.springframework.security.web.authentication.logout.LogoutFilter@7f9fc8bd
     * , org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@4086d8fb
     * , org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@513b52af
     * , org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@3166f664
     * , org.springframework.security.web.authentication.www.BasicAuthenticationFilter@c386958
     * , org.springframework.security.web.savedrequest.RequestCacheAwareFilter@45f756e6
     * , org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7d247660
     * , org.springframework.security.web.authentication.AnonymousAuthenticationFilter@47ac613b
     * , org.springframework.security.web.access.ExceptionTranslationFilter@35c9a231
     * , org.springframework.security.web.access.intercept.AuthorizationFilter@3bec5821]
     *
     *
     */

    /**
     * filter经过UsernamePasswordAuthenticationFilter的时候会
     *两个参数List<AuthenticationProvider> providers, AuthenticationManager parent，
     * 先便利providers，没有找到对应的用户登陆方式，则会去找parent的登录方式
     * 下面配置了数据库和缓存同时生效的方式
     * @return
     */

    /**
     * 比下面多了一个验证码校验
     * @return
     */
    AuthenticationManager myAuthenticationProviders(){
        List<AuthenticationProvider> providers = new ArrayList<>();
        //数据库，此处可以省略了，因为验证码校验继承了DaoAuthenticationProvider
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(myUserService);
        providers.add(authenticationProvider);
        //缓存
        DaoAuthenticationProvider authenticationProvider1 = new DaoAuthenticationProvider();
        authenticationProvider1.setUserDetailsService(usInMemoryUserDetailsManager2());
        providers.add(authenticationProvider1);
        //短信
        SmsAuthenticationProvider smsAuthenticationProvider = new SmsAuthenticationProvider();
        //todo 先写成userService，我觉得也可以新建一个类似userservice的类，去实现手机号查询数据库
        smsAuthenticationProvider.setMyUserService(myUserService);
        providers.add(smsAuthenticationProvider);

        //todo 打开验证码校验，上面的数据库要关掉，不然直接走DaoAuthenticationProvider，目前还没排查出为什么
        //验证码校验
        //此处只是实现验证码的一种方式，如果注释了这段代码就不会有验证码验证，请打开上面的数据库authenticationProvider
//        KaptchaAuthenticationProvider kaptchaAuthenticationProvider = new KaptchaAuthenticationProvider();
//        kaptchaAuthenticationProvider.setUserDetailsService(myUserService);
//        providers.add(kaptchaAuthenticationProvider);

        ProviderManager providerManager = new ProviderManager(providers,parentAuthenticationProvider());
        return providerManager;
    }

    //上面的多了一个验证码校验
//    AuthenticationManager authenticationProvider(){
//        List<AuthenticationProvider> providers = new ArrayList<>();
//        //数据库
//        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
//        authenticationProvider.setUserDetailsService(userService);
//        providers.add(authenticationProvider);
//        //缓存
//        DaoAuthenticationProvider authenticationProvider1 = new DaoAuthenticationProvider();
//        authenticationProvider1.setUserDetailsService(usInMemoryUserDetailsManager2());
//        providers.add(authenticationProvider1);
//
//        ProviderManager providerManager = new ProviderManager(providers,parentAuthenticationProvider());
//        return providerManager;
//    }
    AuthenticationManager parentAuthenticationProvider(){
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setUserDetailsService(usInMemoryUserDetailsManager1());

        ProviderManager providerManager = new ProviderManager(authenticationProvider);
        return providerManager;
    }
    UserDetailsService usInMemoryUserDetailsManager1(){
        return new InMemoryUserDetailsManager(
                User.withUsername("test1")
                        .password("{noop}123")
                        .roles("admin")
                        .build());
    }
    UserDetailsService usInMemoryUserDetailsManager2(){
        return new InMemoryUserDetailsManager(
                User.withUsername("test2")
                        .password("{noop}123")
                        .roles("admin")
                        .build());
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authenticationManager(myAuthenticationProviders())
                //禁止使用session
                .sessionManagement(o->o.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                //所有请求有需要认证之后才能访问
                .authorizeHttpRequests(req->req
                        //这两种 和 下面的@bean  WebSecurityCustomizer
                        //登录不登录都能访问
                        .requestMatchers("/hello2").permitAll()
                        .requestMatchers("/vc.jpg").permitAll()
                        .requestMatchers("/sendSms").permitAll()
                        //只允许匿名访问
//                        .requestMatchers("/hello2").anonymous()
                        .anyRequest().authenticated()
                )
                //配置自定义表单登录，放行
                .formLogin(f->f
                        //页面默认账号字段
                        .usernameParameter("uname")
                        //页面默认密码字段
                        .passwordParameter("pwd")
                        //默认登录页
                        .loginPage("/login_1.html")
                        //默认登录接口
                        .loginProcessingUrl("/login1")
//                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
//                        .successForwardUrl("/successForwardUrl")
//                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
//                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
//                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
//                        .defaultSuccessUrl("/defaultSuccessUrl",true)
//                        //
//                        .failureForwardUrl("/failureForwardUrl")
//                        //
//                        .failureUrl("/failureUrl")
                        //此方法可以自定义登录成功后的处理逻辑
                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
                            String token = JwtUtil.createToken();
                            //放入redis
                            String key = authentication.getName()+":"+token;
                            redisTemplate.opsForValue().set(key,authentication.getName());
                            //设置过期时间
                            redisTemplate.expire(key,10, TimeUnit.MINUTES);
                            httpServletResponse.setContentType("application/json;charset=utf-8");
                            //获取当前登录请求的对象
                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(token)));
                            httpServletResponse.getWriter().flush();
                            httpServletResponse.getWriter().close();
                        })
                        .failureHandler((httpServletRequest,httpServletResponse,exception)->{
                            httpServletResponse.setContentType("application/json;charset=utf-8");
                            //获取当前登录请求的对象
                            httpServletResponse.getWriter().write("登录失败:"+exception.getMessage());
                            httpServletResponse.getWriter().flush();
                            httpServletResponse.getWriter().close();
                        })
                        .permitAll())
                .logout(l->l
                        //注销登录的地址
                        .logoutUrl("/logout1")
                        //销毁httpsession，默认是true
                        .invalidateHttpSession(true)
                        //清除cookie
                        .deleteCookies()
                        //清除认证信息
                        .clearAuthentication(true)
                                .logoutSuccessHandler((request,response,authentication)->{
                                    String token = request.getHeader(CommonConstants.authorization).replaceAll(CommonConstants.bearer + " ", "");
                                    String key = authentication.getName() + ":" + token;
                                    //删除令牌
                                    redisTemplate.delete(key);
                                    log.info(authentication.getName()+"退出登录成功");
                                })
                        //注销成功之后的跳转页面
//                        .logoutSuccessUrl("/logout_1.html")
                        .logoutSuccessUrl("/login_1.html")
                        .permitAll()
                )
                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
               // .csrf(c->c.disable())
                .csrf(AbstractHttpConfigurer::disable)
                .addFilterBefore(jsonFilter(), UsernamePasswordAuthenticationFilter.class)
                //自己想的这样，短信也放在usernamepassword前面
                .addFilterBefore(smsAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(jwtFilter, SecurityContextHolderFilter.class)
        ;
        return http.build();
    }
/*
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                //所有请求有需要认证之后才能访问
                .authorizeHttpRequests(req->req

                        //这两种 和 下面的@bean  WebSecurityCustomizer
                        //登录不登录都能访问
//                        .requestMatchers("/hello2").permitAll()
                        //只允许匿名访问
//                        .requestMatchers("/hello2").anonymous()

                        .anyRequest().authenticated()

                )
                //配置自定义表单登录，放行
                .formLogin(f->f
                        //页面默认账号字段
                        .usernameParameter("uname")
                        //页面默认密码字段
                        .passwordParameter("pwd")
                        //默认登录页
                        .loginPage("/login_1.html")
                        //默认登录接口
                        .loginProcessingUrl("/login1")
//                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
//                        .successForwardUrl("/successForwardUrl")
//                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
//                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
//                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
//                        .defaultSuccessUrl("/defaultSuccessUrl",true)
//                        //
//                        .failureForwardUrl("/failureForwardUrl")
//                        //
//                        .failureUrl("/failureUrl")
                        //此方法可以自定义登录成功后的处理逻辑
                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
                            httpServletResponse.setContentType("application/json;charset=utf-8");
                            //获取当前登录请求的对象
                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(authentication)));
                            httpServletResponse.getWriter().flush();
                            httpServletResponse.getWriter().close();
                        })
                        .failureHandler((httpServletRequest,httpServletResponse,exception)->{
                            httpServletResponse.setContentType("application/json;charset=utf-8");
                            //获取当前登录请求的对象
                            httpServletResponse.getWriter().write("登录失败:"+exception.getMessage());
                            httpServletResponse.getWriter().flush();
                            httpServletResponse.getWriter().close();
                        })
                        .permitAll())
                .logout(l->l
                        //注销登录的地址
                        .logoutUrl("/logout1")
                        //销毁httpsession，默认是true
                        .invalidateHttpSession(true)
                        //清除cookie
                        .deleteCookies()
                        //清除认证信息
                        .clearAuthentication(true)
                        //注销成功之后的跳转页面
//                        .logoutSuccessUrl("/logout_1.html")
                        .logoutSuccessUrl("/login_1.html")
                        .permitAll()
                )
                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
               // .csrf(c->c.disable())
                .csrf(AbstractHttpConfigurer::disable)
        ;
        return http.build();
    }
*/




    /**
     *
     *   //登录不登录都能访问
     * //                        .requestMatchers("/hello2").permitAll()
     *                         //只允许匿名访问
     * //                        .requestMatchers("/hello2").anonymous()
     * 这种方式是直接不执行filterChainProxy，而上面的两个是执行filterChainProxy的
     *
     * 一般前端静态页面css js等等 可以使用这种方案去放行
     * 接口匿名建议使用上面两种方式
     * @return
     */
//    @Bean
//    WebSecurityCustomizer webSecurityCustomizer(){
//        return web -> web.ignoring().requestMatchers(
//                "/hello2"
//        );
//    }


//    @Bean
//    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//        http
//                //所有请求有需要认证之后才能访问
//                .authorizeHttpRequests(req->req
//                        //登录不登录都能访问
////                        .requestMatchers("/hello2").permitAll()
//                        //只允许匿名访问
//                        .requestMatchers("/hello2").anonymous()
//                        .anyRequest().authenticated()
//
//                )
//                //配置自定义表单登录，放行
//                .formLogin(f->f
//                        //页面默认账号字段
//                        .usernameParameter("uname")
//                        //页面默认密码字段
//                        .passwordParameter("pwd")
//                        //默认登录页
//                        .loginPage("/login_1.html")
//                        //默认登录接口
//                        .loginProcessingUrl("/login1")
////                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
////                        .successForwardUrl("/successForwardUrl")
////                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
////                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
////                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
//////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
////                        .defaultSuccessUrl("/defaultSuccessUrl",true)
////                        //
////                        .failureForwardUrl("/failureForwardUrl")
////                        //
////                        .failureUrl("/failureUrl")
//                        //此方法可以自定义登录成功后的处理逻辑
//                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(authentication)));
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .failureHandler((httpServletRequest,httpServletResponse,exception)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write("登录失败:"+exception.getMessage());
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .permitAll())
//                .logout(l->l
//                        //注销登录的地址
//                        .logoutUrl("/logout1")
//                        //销毁httpsession，默认是true
//                        .invalidateHttpSession(true)
//                        //清除cookie
//                        .deleteCookies()
//                        //清除认证信息
//                        .clearAuthentication(true)
//                        //注销成功之后的跳转页面
////                        .logoutSuccessUrl("/logout_1.html")
//                        .logoutSuccessUrl("/login_1.html")
//                        .permitAll()
//                )
//                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
//               // .csrf(c->c.disable())
//                .csrf(AbstractHttpConfigurer::disable)
//        ;
//        return http.build();
//    }
//

//    @Bean
//    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//        http
//                //所有请求有需要认证之后才能访问
//                .authorizeHttpRequests(req->req.anyRequest().authenticated())
//                //配置自定义表单登录，放行
//                .formLogin(f->f
//                        //页面默认账号字段
//                        .usernameParameter("uname")
//                        //页面默认密码字段
//                        .passwordParameter("pwd")
//                        //默认登录页
//                        .loginPage("/login_1.html")
//                        //默认登录接口
//                        .loginProcessingUrl("/login1")
////                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
////                        .successForwardUrl("/successForwardUrl")
////                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
////                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
////                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
//////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
////                        .defaultSuccessUrl("/defaultSuccessUrl",true)
////                        //
////                        .failureForwardUrl("/failureForwardUrl")
////                        //
////                        .failureUrl("/failureUrl")
//                        //此方法可以自定义登录成功后的处理逻辑
//                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(authentication)));
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .failureHandler((httpServletRequest,httpServletResponse,exception)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write("登录失败:"+exception.getMessage());
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .permitAll())
//                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
//               // .csrf(c->c.disable())
//                .csrf(AbstractHttpConfigurer::disable)
//        ;
//        return http.build();
//    }


//    @Bean
//    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//        http
//                //所有请求有需要认证之后才能访问
//                .authorizeHttpRequests(req->req.anyRequest().authenticated())
//                //配置自定义表单登录，放行
//                .formLogin(f->f
//                        //页面默认账号字段
//                        .usernameParameter("uname")
//                        //页面默认密码字段
//                        .passwordParameter("pwd")
//                        //默认登录页
//                        .loginPage("/login_1.html")
//                        //默认登录接口
//                        .loginProcessingUrl("/login1")
////                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
////                        .successForwardUrl("/successForwardUrl")
////                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
////                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
////                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
//////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
////                        .defaultSuccessUrl("/defaultSuccessUrl",true)
////                        //
////                        .failureForwardUrl("/failureForwardUrl")
////                        //
////                        .failureUrl("/failureUrl")
//                        //此方法可以自定义登录成功后的处理逻辑
////                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
////                            httpServletResponse.setContentType("application/json;charset=utf-8");
////                            //获取当前登录请求的对象
////                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(authentication)));
////                            httpServletResponse.getWriter().flush();
////                            httpServletResponse.getWriter().close();
////                        })
////                        .failureHandler((httpServletRequest,httpServletResponse,authentication)->{
////                            httpServletResponse.setContentType("application/json;charset=utf-8");
////                            //获取当前登录请求的对象
////                            httpServletResponse.getWriter().write("登录失败");
////                            httpServletResponse.getWriter().flush();
////                            httpServletResponse.getWriter().close();
////                        })
//                        .successHandler(savedRequestAwareAuthenticationSuccessHandler())
//                        .permitAll())
//                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
//               // .csrf(c->c.disable())
//                .csrf(AbstractHttpConfigurer::disable)
//        ;
//        return http.build();
//    }

//    //设置调用登录接口传入的接口上 带有target=的参数，然后参数有值，则会登录成功跳转到对应的接口地址
//    AuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler(){
//        SavedRequestAwareAuthenticationSuccessHandler savedRequestAwareAuthenticationSuccessHandler = new SavedRequestAwareAuthenticationSuccessHandler();
//        savedRequestAwareAuthenticationSuccessHandler.setTargetUrlParameter("target");
//        return savedRequestAwareAuthenticationSuccessHandler;
//
//    }


//    @Bean
//    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//        http
//                //所有请求有需要认证之后才能访问
//                .authorizeHttpRequests(req->req.anyRequest().authenticated())
//                //配置自定义表单登录，放行
//                .formLogin(f->f
//                        //页面默认账号字段
//                        .usernameParameter("uname")
//                        //页面默认密码字段
//                        .passwordParameter("pwd")
//                        //默认登录页
//                        .loginPage("/login_1.html")
//                        //默认登录接口
//                        .loginProcessingUrl("/login1")
////                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
////                        .successForwardUrl("/successForwardUrl")
////                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
////                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
////                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
//////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
////                        .defaultSuccessUrl("/defaultSuccessUrl",true)
////                        //
////                        .failureForwardUrl("/failureForwardUrl")
////                        //
////                        .failureUrl("/failureUrl")
//                        //此方法可以自定义登录成功后的处理逻辑
//                        .successHandler((httpServletRequest,httpServletResponse,authentication)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write(JSONUtil.toJsonStr(R.ok(authentication)));
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .failureHandler((httpServletRequest,httpServletResponse,authentication)->{
//                            httpServletResponse.setContentType("application/json;charset=utf-8");
//                            //获取当前登录请求的对象
//                            httpServletResponse.getWriter().write("登录失败");
//                            httpServletResponse.getWriter().flush();
//                            httpServletResponse.getWriter().close();
//                        })
//                        .permitAll())
//                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
//               // .csrf(c->c.disable())
//                .csrf(AbstractHttpConfigurer::disable)
//        ;
//        return http.build();
//    }
//    @Bean
//    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
//        http
//                //所有请求有需要认证之后才能访问
//                .authorizeHttpRequests(req->req.anyRequest().authenticated())
//                //配置自定义表单登录，放行
//                .formLogin(f->f
//                        //页面默认账号字段
//                        .usernameParameter("uname")
//                        //页面默认密码字段
//                        .passwordParameter("pwd")
//                        //默认登录页
//                        .loginPage("/login_1.html")
//                        //默认登录接口
//                        .loginProcessingUrl("/login1")
//                        //服务端跳转（用的不多，一般都是客户端跳转，不推荐，用户页面刷新会存在问题。服务端跳转，上一个请求是get则跳转的是get，反之post-post）
//                        .successForwardUrl("/successForwardUrl")
//                        //客户端跳转，第二个参数表示是否总是使用这个跳转地址
//                        //默认情况下为false，如果访问存在缓存的请求，则登录成功之后，跳转到缓存的地址，否则才跳转到配置的地址
//                        //如果第二个请求为true，则不考虑缓存的请求，登陆成功后直接跳转到defaultSuccessUrl
////                        .defaultSuccessUrl("/defaultSuccessUrl",false)
//                        .defaultSuccessUrl("/defaultSuccessUrl",true)
//                        //
//                        .failureForwardUrl("/failureForwardUrl")
//                        //
//                        .failureUrl("/failureUrl")
//                        //
//                        .permitAll())
//                //关闭csrf校验，本质上就是从过滤器链中去除csrfFilter
//               // .csrf(c->c.disable())
//                .csrf(AbstractHttpConfigurer::disable)
//        ;
//        return http.build();
//    }
//    @Bean
//    public SecurityFilterChain securityFilterChain() {
//        RequestMatcher requestMatcher = new AntPathRequestMatcher("/**");
//        List<Filter> filters = new ArrayList<>();
//        //SecurityFilterChain只有一个实现类DefaultSecurityFilterChain
//        DefaultSecurityFilterChain defaultSecurityFilterChain = new DefaultSecurityFilterChain(requestMatcher,filters);
//        return defaultSecurityFilterChain;
//    }
}
